#include <iostream>
#include <fstream>
#include <cstring>
#include <nng/nng.h>
#include <nng/protocol/reqrep0/req.h>
#include <thread>
#include <vector>

constexpr int BUFFER_SIZE = 4096;

void fatal(const char* func, int rv) {
    std::cerr << func << ": " << nng_strerror(rv) << std::endl;
    exit(1);
}

void doDownload(const char* filename) {
    nng_socket sock;
    int rv;
    // get thread id
    std::thread::id thread_id = std::this_thread::get_id();

    if ((rv = nng_req0_open(&sock)) != 0) {
        fatal("nng_req0_open", rv);
    }
    if ((rv = nng_dial(sock, "tcp://127.0.0.1:5555", nullptr, 0)) != 0) {
    //if ((rv = nng_dial(sock, "tcp://127.0.0.1:10000", nullptr, 0)) != 0) {
        fatal("nng_dial", rv);
    }

    nng_msg* msg;
    if ((rv = nng_msg_alloc(&msg, 0)) != 0) {
        fatal("nng_msg_alloc", rv);
    }
    nng_msg_append(msg, filename, strlen(filename));

    std::cout << "[t:"<< thread_id << "]send msg to server." << std::endl;
    // 发送请求消息给服务器
    if ((rv = nng_sendmsg(sock, msg, 0)) != 0) {
        fatal("nng_sendmsg", rv);
    }

    // 接收服务器响应消息
    if ((rv = nng_recvmsg(sock, &msg, 0)) != 0) {
        fatal("nng_recvmsg", rv);
    }

    // 检查是否收到错误消息
    const char* response = static_cast<const char*>(nng_msg_body(msg));
    if (std::string(response) == "File not found") {
        std::cout << "[t:"<< thread_id << "]File not found on the server." << std::endl;
    } else {
        std::cout << "[t:" << thread_id << "]File downloaded successfully." << std::endl;
        // 保存文件
        // std::ofstream output_file("downloaded_file.txt", std::ios::binary);
        // if (!output_file) {
        //     std::cout << "Failed to open file for writing." << std::endl;
        // } else {
        //     size_t msg_size = nng_msg_len(msg);
        //     output_file.write(response, msg_size);
        //     output_file.close();
        //     std::cout << "File downloaded successfully." << std::endl;
        // }
    }

    nng_msg_free(msg);
    nng_close(sock);
}

int main(int argc, char* argv[]) {
    //get filename from argv[1]
    if (argc != 2) {
        std::cerr << "Usage: " << argv[0] << " <filename>" << std::endl;
        return 1;
    }

    const char* filename = argv[1];
    std::cout << "client request filename: " << filename << std::endl;

    // create 10 threads to download file
    std::vector<std::thread> threads;
    for (int i = 0; i < 10; i++) {
        threads.emplace_back(doDownload, filename);
    }
    // wait for all threads to finish
    for (auto& thread : threads) {
        thread.join();
    }
    
    return 0;
}